package com.profgj.profgj.controller;

import com.profgj.profgj.entity.PublishPolicyFile;
import com.profgj.profgj.enums.ServerStatus;
import com.profgj.profgj.service.PublishPolicyFileService;
import com.profgj.profgj.utils.EmptyUtils;
import com.profgj.profgj.utils.ReturnOperator;
import com.profgj.profgj.validater.PublishPolicyFileValidator;
import com.profgj.profgj.vo.EmptyObject;
import com.profgj.profgj.vo.ResultMsg;
import com.profgj.profgj.vo.ReturnResult;
import io.swagger.annotations.*;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 政策文件发布(控制层)
 */
@RestController
@RequestMapping("/publishfile")
@Scope("session")
@Api(tags = {"政策文件发布"},description = "政策文件发布")
public class PublishPolicyFileController {

    /**
     * 政策文件服务对象
     */
    @Resource
    private PublishPolicyFileService publishPolicyFileService;

    /**
     * 文件上传的默认路径,作为上传临时路径
     */
    @Value("${spring.servlet.multipart.location}")
    private String tempPath = null;

    /**
     * 返回空对象的替代品
     */
    private EmptyObject emptyObject = new EmptyObject();

    /**
     * 临时上传文件位置变量
     */
    private String tempfilename;

    /**
     * 政策文件存放目录
     */
    @Value("${system.publishFilePath}")
    private String publishFilePath = null;


    /**
     * 初始化设置校验器
     * @param binder    校验器绑定对象
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 设置校验器
        binder.setValidator(new PublishPolicyFileValidator());
    }


    /**
     * id获取政策文件对象
     * @param id    政策文件id
     * @return
     */
    @GetMapping("/file/{id}")
    @ApiOperation(value = "id获取政策文件对象",produces = "application/json",consumes = "application/json")
    @ApiImplicitParam(name = "id",value = "政策文件id", required = true, dataType = "Long", paramType = "Long", dataTypeClass = Long.class)
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> queryPublishPolicyFileByIdMethod(@PathVariable("id")Long id) {

        // id参数校验
        if (!EmptyUtils.isLongEmpty(id)) {
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // id 查询政策文件
        PublishPolicyFile publishPolicyFile = publishPolicyFileService.queryById(id);

        // 检查查询结果
        if (!EmptyUtils.isPublishPolicyFile(publishPolicyFile)) {
            return ReturnOperator.createResultMsg("", ServerStatus.QUERY_MESSAGE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.QUERY_MESSAGE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), publishPolicyFile, HttpStatus.OK);
    }

    /**
     * 分页查询政策文件
     * @param draw    绘制次数
     * @param start    查询起始位置
     * @param length     查询条数
     * @param search     查询关键字
     * @return
     */
    @GetMapping("/list")
    @ApiOperation(value = "分页查询政策文件",produces = "application/json",consumes = "application/json")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "draw",value = "绘制次数", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "start",value = "查询起始位置", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "length",value = "查询条数", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "search",value = "查询关键字", required = true, dataType = "String", paramType = "String", dataTypeClass = String.class)
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ReturnResult> queryPublishPolicyFileListMethod(Integer draw,
                                                                   Integer start,
                                                                   Integer length,
                                                                   String search,
                                                                   @ApiIgnore HttpSession session) {

        // 分页参数校验
        if (!EmptyUtils.isIntegerEmpty(start) && !EmptyUtils.isIntegerEmpty(length)) {
            return ReturnOperator.createResultMsg(draw, 0,0,
                    new ArrayList(), HttpStatus.OK);
        }
        List<PublishPolicyFile> publishPolicyFiles = null;
        Integer totalCount = 0;
        if (EmptyUtils.isStringEmpty(search)) {
            // 计算总记录数
            totalCount = publishPolicyFileService.queryAllByKeyword(search).size();
            // 分页查询政策文件列表
            publishPolicyFiles = publishPolicyFileService.queryAllByLimitAndKeyword(search, start, length);
        } else {
            // 计算总记录数 存在优化问题可以使用COUNT函数
            totalCount = publishPolicyFileService.queryAll().size();
            // 分页查询政策文件列表
            publishPolicyFiles = publishPolicyFileService.queryAllByLimit(start, length);
        }


        // 查询结果校验
        if (!EmptyUtils.isPublishPolicyFileList(publishPolicyFiles)) {
            return ReturnOperator.createResultMsg(draw, 0,0,
                    new ArrayList(), HttpStatus.OK);
        }

        // 对文件的URL进行处理
        for(PublishPolicyFile publishPolicyFile : publishPolicyFiles){
            if(publishPolicyFile.getFilePath()!=null && !(publishPolicyFile.getFilePath().isEmpty())){
                String[] split = publishPolicyFile.getFilePath().split("/static");
                publishPolicyFile.setFilePath(split[1]);
            }
        }

        // 返回数据
        return ReturnOperator.createResultMsg(draw, 0, 0,
                publishPolicyFiles, HttpStatus.OK);
    }


    /**
     * 添加政策文件
     * @param title     标题
     * @param content   内容
     * @param file      文件
     * @param session
     * @return
     */
    @PostMapping("/file")
    @ApiOperation(value = "添加政策文件",produces = "application/json",consumes = "muiltipart-file/form-data")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "title",value = "标题", required = true, dataType = "String", paramType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "content",value = "内容", required = true, dataType = "String", paramType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "file",value = "文件", required = true, dataType = "Part", paramType = "Part", dataTypeClass = Part.class)
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> addPublishPolicyFileMethod(String title, String content,Part file, @ApiIgnore HttpSession session) {

        /**
         * 参数校验
         */
        if (!EmptyUtils.isStringEmpty(title)){
            return ReturnOperator.createResultMsg("", ServerStatus.PARAM_NOT_EMPTY, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 临时文件名

        PublishPolicyFile publishPolicyFile = new PublishPolicyFile();

        if(!file.getSubmittedFileName().isEmpty()) {
            try{
                // 写入文件 实际写入到application.yml中配置的 classpath下的tempupload下
                // 也就是main目录下的resources下的static/tempload 存放临时位置
                tempfilename = file.getSubmittedFileName();
                file.write(tempfilename);
            }catch (Exception e) {
                e.printStackTrace();
            }

            // 取已经登录的用户Id
            Integer user_id = Integer.parseInt(String.valueOf(session.getAttribute("user_id")));

            // 拼接 /51/2021-07-16/
            String str_userid_Date ="" + user_id + "/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";

            // 拼接目标目录对象
            File folder = new File(publishFilePath + str_userid_Date);
            // 不存在目录则创建
            if (!folder.exists()){
                folder.mkdirs();
            }

            // 获取扩展名
            String extName = file.getSubmittedFileName().substring(file.getSubmittedFileName().indexOf("."));
            // 拼接文件名 51-2021-07-16-11-04-22***
            String fileName = "" + user_id + "-" + new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(new Date()) + extName;

            // 创建目录文件对象
            File desFile = new File(publishFilePath + str_userid_Date + fileName);

            try{
                // 将临时文件移动到目标存放位置
                FileUtils.moveFile(new File(tempPath + tempfilename), desFile);
            }catch (IOException e) {
                e.printStackTrace();
            }

            publishPolicyFile.setFilePath(publishFilePath + str_userid_Date + fileName);
        }


        /**
         * 创建政策文件发布对象
         */
        publishPolicyFile.setTitle(title);
        publishPolicyFile.setContent(content);
        publishPolicyFile.setDeleted(0);
        publishPolicyFile.setPublishDate(new Date());

        // 添加到数据库
        PublishPolicyFile publishPolicyFile_new = publishPolicyFileService.insert(publishPolicyFile);

        // 判断添加数据库操作后的记录是否成功
        if (!EmptyUtils.isPublishPolicyFile(publishPolicyFile_new)){
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_INSERT_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_INSERT_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), publishPolicyFile_new, HttpStatus.OK);
    }

    /**
     * 更新政策文件
     * @param publishPolicyFile     政策文件对象
     * @param errors    错误文件存储对象
     * @return
     */
    @PutMapping("/file")
    @ApiOperation(value = "更新政策文件",produces = "application/json",consumes = "application/json")
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> updatePublishPolicyFileMethod(@Valid @RequestBody PublishPolicyFile publishPolicyFile, @ApiIgnore Errors errors,@ApiIgnore HttpSession session) {

        // 对象参数校验
        if (errors.hasErrors()) {
            List<ObjectError> oes = errors.getAllErrors();
            for (ObjectError oe : oes) {
                if (oe instanceof FieldError) {
                    FieldError fe = (FieldError) oe;
                    return ReturnOperator.createResultMsg("", fe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                } else {
                    return ReturnOperator.createResultMsg("", oe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                }
            }
        }

        // 政策文件id查询 政策文件信息
        PublishPolicyFile publishPolicyFile_q = publishPolicyFileService.queryById(publishPolicyFile.getId());

        /**
         * 临时文件操作
         */
        // 取到resources/static/tempupload/下路径
        String resources_tmp = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "/static/tempupload";
        // 目标路径
        String resources = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "/static/upload";
        // 构建临时文件对象
        File file = new File(resources_tmp + tempfilename);

        // 判断临时上传的文件不存在情况下
        if (!file.exists()) {
            return ReturnOperator.createResultMsg("", "文件临时上传已过期,请在1分钟之内处理", ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }


        /**
         * 将老文件删除
         */
        // 构建老的文件对象
        File old_file = new File(resources + publishPolicyFile_q.getFilePath());
        // 判断是否存在,存在则删除
        if (old_file.exists()) {
            // 删除文件
            old_file.delete();
        }


        /**
         * 将临时文件移动到目标位置
         */
        // 设置日期时间格式
        SimpleDateFormat datef = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat timef = new SimpleDateFormat("HH:mm");
        // 获取当前系统时间对象
        Date date = new Date();
        // 拼接 文件夹日期时间名称  例如:2021-6-25-15-55
        String new_path = "/" + datef.format(date) + "-" + timef.format(date) + "/";
        // 构建文件夹对象
        File upload_folder = new File(resources_tmp + new_path);
        // 判断文件夹是否存在
        if (!upload_folder.exists()) {
            // 不存在则创建文件夹
            upload_folder.mkdirs();
        }
        // 构造目标存在文件对象   resources目录+企业id+当前系统日期时间+目标文件名
        File upload_file = new File(resources +  new_path + tempfilename);
        try{
            // 将临时文件移动到目标存放位置
            FileUtils.moveFile(file, upload_file);
        }catch (IOException e) {
            e.printStackTrace();
        }

        // 将上传的路径保存到对象中
        publishPolicyFile.setFilePath(new_path + tempfilename);

        // 更新到数据库中
        PublishPolicyFile publishPolicyFile_new = publishPolicyFileService.update(publishPolicyFile);

        // 判断数据插入是否成功
        if(!EmptyUtils.isPublishPolicyFile(publishPolicyFile_new)) {
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_UPDATE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_UPDATE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), publishPolicyFile_new, HttpStatus.OK);
    }


    /**
     * id删除政策文件
     * @param id    政策文件id
     * @return
     */
    @DeleteMapping("/file/{id}")
    @ApiOperation(value = "id删除政策文件",produces = "application/json",consumes = "application/json")
    @ApiImplicitParam(name = "id",value = "政策文件id", required = true,dataType = "Long", paramType = "Long", dataTypeClass = Long.class)
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> deletePublishPolicyFileByIdMethod(@PathVariable("id") Long id,@ApiIgnore HttpSession session) {

        // id参数校验
        if (!EmptyUtils.isLongEmpty(id)) {
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 删除文件
        PublishPolicyFile publishPolicyFile = publishPolicyFileService.queryById(id);

        // 判断政策文件上传的路径是否为空
        if (publishPolicyFile.getFilePath() != null){
            File delFile = new File(publishPolicyFile.getFilePath());
            // 文件存在则删除
            if(delFile.exists()){
                delFile.delete();
            }
        }

        // id删除政策文件判断不成功
        if (!publishPolicyFileService.deleteById(publishPolicyFile.getId())) {
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_DELETE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_DELETE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), new Boolean(true), HttpStatus.OK);
    }


    /**
     * 政策文件上传接口
     * @param file
     * @return
     */
    @PostMapping("/file/upload")
    @ApiOperation(value = "政策文件上传接口",produces = "application/json",consumes = "muiltipart-file/form-data")
    @ApiImplicitParam(name = "file",value = "上传文件对象", required = true,dataType = "Part", paramType = "Part", dataTypeClass = Part.class)
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> uploadFile (Part file) {

        // 上传文件校验
        if(!EmptyUtils.isNotFile(file)) {
            return ReturnOperator.createResultMsg("", ServerStatus.FILE_UPLOAD_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        try{
            // 写入文件 实际写入到application.yml中配置的 classpath下的tempupload下
            // 也就是main目录下的resources下的static/tempload 存放临时位置
            tempfilename = file.getSubmittedFileName();
            file.write(tempfilename);
        }catch (Exception e) {
            e.printStackTrace();
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.FILE_UPLOAD_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), new Boolean(true), HttpStatus.OK);
    }
}
